//
// Created by mio on 25-4-14.
//

#include "TcpConnection.h"

#include <unistd.h>
#include <iostream>

TcpConnection::TcpConnection(TaskScheduler* task_scheduler, int sockfd) :
    task_scheduler_(task_scheduler),
    read_buffer_(new BufferReader()),
    write_buffer_(new BufferWriter()),
    channel_(std::make_shared<Channel>(sockfd))
{
    is_closed_ = false;
    // --- 将 Channel 的事件回调连接到 TcpConnection 的处理方法 ---
    channel_->SetReadCallback([this](){ this->HandleRead(); });
    channel_->SetWriteCallback([this](){ this->HandleWrite(); });
    channel_->SetCloseCallback([this](){ this->HandleClose(); });
    channel_->SetErrorCallback([this](){ this->HandleError(); });

    // 设置套接字属性
    SocketUtil::SetNonBlock(sockfd);                        // 设置为非阻塞模式，非常重要！
    SocketUtil::SetSendBufSize(sockfd, 1024 * 100);     // 尝试设置发送缓冲区大小 (可选)
    SocketUtil::SetKeepAlive(sockfd);                       // 开启 TCP KeepAlive (可选)
    // --- 激活 Channel ---
    // 默认开始关心可读事件，以便接收客户端数据
    channel_->EnableRead();
    task_scheduler_->UpdateChannel(channel_);
}

TcpConnection::~TcpConnection()
{
    int fd = channel_->GetSocket();
    if (fd > 0)
    {
        std::cout << "close : " << fd << "\n";
        ::close(fd);
    }
}

void TcpConnection::Send(std::shared_ptr<char> data, uint32_t size)
{
    if (!is_closed_)
    {
        mtx_.lock();
        write_buffer_->Append(data, size);
        mtx_.unlock();
        // if (!channel_->IsWriteEvent()) {
        //     // 启用可写事件监听
        //     channel_->EnableWrite();
        //     // 通知 TaskScheduler 更新 Channel 的监听状态
        //     // 当 socket 可写时，事件循环会调用 HandleWrite()
        //     // 走事件通知一轮后回调 TcpConnection::HandleWrite()
        //     task_scheduler_->UpdateChannel(channel_);
        // }
        this->HandleWrite(); // 发送
    }
}

void TcpConnection::Send(const char* data, uint32_t size)
{
    if (!is_closed_)
    {
        mtx_.lock();
        write_buffer_->Append(data, size);
        mtx_.unlock();
        // if (!channel_->IsWriteEvent()) {
        //     channel_->EnableWrite();
        //     task_scheduler_->UpdateChannel(channel_);
        // }
        this->HandleWrite(); // 发送
    }
}

void TcpConnection::DisConnect()
{
    std::lock_guard<std::mutex> lock(mtx_);
    this->Close();
}

void TcpConnection::HandleRead()
{
    {
        std::lock_guard<std::mutex> lock(mtx_);
        if (is_closed_) return;

        // 从 socket 读取数据到 read_buffer_
        int ret = read_buffer_->Read(channel_->GetSocket());
        if (ret < 0)
        {
            this->Close();
            return;
        }
    }

    // 如果设置了用户读取回调 (readCb_)
    if (readCb_)
    {
        // 用户回调返回 false 表示希望关闭连接
        bool ret = readCb_(shared_from_this(), *read_buffer_);
        if (!ret)
        {
            std::lock_guard<std::mutex> lock(mtx_);
            this->Close();
        }
    }

    // /* 测试用的简单Echo逻辑 */
    // std::string data;
    // uint32_t size = read_buffer_->ReadAll(data);
    // if (size)
    // {
    //     this->Send(data.data(), data.size());
    // }
}

void TcpConnection::HandleWrite()
{
    if (is_closed_) return;
    if (!mtx_.try_lock()) return;
    int ret = 0; // 记录最后一次 send 的结果
    bool empty = false;
    ret = write_buffer_->Send(channel_->GetSocket());
    if (ret < 0)
    {
        this->Close();
        mtx_.unlock();
        return;
    }
    empty = write_buffer_->IsEmpty();

    // --- 根据缓冲区状态调整写事件监听 ---
    if (empty)   // 如果缓冲区已空
    {
        // 并且 Channel 当前仍在监听可写事件
        if (channel_->IsWriteEvent())
        {
            // 停止监听可写事件，避免不必要的 epoll 唤醒 (CPU 消耗)
            channel_->DisableWrite();
            task_scheduler_->UpdateChannel(channel_);
        }
    }
    else // 如果缓冲区非空 (意味着上次 send 没有发完所有数据，可能遇到了 EAGAIN)
    {
        // 确保仍在监听可写事件 (理论上应该已经在监听，因为 HandleWrite 被调用了)
        // 这个检查可能是防御性的
        if (!channel_->IsWriteEvent())
        {
            channel_->EnableWrite();
            task_scheduler_->UpdateChannel(channel_);
        }
    }
    mtx_.unlock();
}

void TcpConnection::HandleClose()
{
    std::lock_guard<std::mutex> lock(mtx_);
    this->Close();
}

void TcpConnection::HandleError()
{
    std::lock_guard<std::mutex> lock(mtx_);
    this->Close();
}

void TcpConnection::Close()
{
    if (!is_closed_)
    {
        is_closed_ = true;
        task_scheduler_->RemoveChannel(channel_);
        if (closeCb_)
        {
            closeCb_(shared_from_this());
        }
        // if (disconnectCb_)
        // {
        //     disconnectCb_(shared_from_this());
        // }
    }
}
